//一个简单的不带泛型参数的阻塞队列
class MyBlockingQueue{
    //这个阻塞队列的底层是一个字符串数组
    private String[] array = null;
    //size 表示当前队列中元素的个数
    private int size = 0;
    //head 和 tail 分别表示队头和队尾的下标
    private int head = 0;
    private int tail = 0;

    public MyBlockingQueue(int capacity){
        this.array = new String[capacity];
    }

    //锁
    private Object locker = new Object();

    //入队
    public void put(String elem) throws InterruptedException{
        synchronized(locker){
            //判断队列是否满了,满了就等待
            while(size >= array.length){
                locker.wait();
            }
            //队列没有满,就入队
            //把新元素放到tail位置
            array[tail] = elem;
            //更新tail
            tail++;
            //如果tail超过了数组的长度,就从头开始
            //相当于一个环形
            if(tail >= array.length){
                tail = 0;
            }
            //更新size
            size++;
            //唤醒 take 中的阻塞
            locker.notify();
        }
    }

    //出队
    public String take() throws InterruptedException{
        synchronized(locker){
            //判断队列是否为空,空了就等待
            while(size == 0){
                locker.wait();
            }
            //队列不为空,就出队
            //把head位置的元素取出来
            String ret = array[head];
            //更新head
            head++;
            //如果head超过了数组的长度,就从头开始
            //相当于一个环形
            if(head >= array.length){
                head = 0;
            }
            //更新size
            size--;
            //唤醒 put 中的阻塞
            locker.notify();
            //返回出队的元素
            return ret;
        }
    }
}
public class Test1 {
    public static void main(String[] args){
        //基于我在上方自建的阻塞队列，实现一个生产者消费者模型
        //创建一个阻塞队列，容量为10
        MyBlockingQueue queue = new MyBlockingQueue(10);

        //创建一个生产者线程
        Thread producer = new Thread(() -> {
            int count = 0;
            try{
                while(true){
                    //生产一个数据
                    String data = "data_" + count;
                    //把数据放到队列中
                    queue.put(data);
                    System.out.println("生产数据: " + data);
                    count++;
                    //休眠一秒
                    Thread.sleep(1000);
                }
            } catch (InterruptedException e){
                e.printStackTrace();
            }
        });

        Thread consumer = new Thread(() -> {
            try{
                while(true){
                    //从队列中取出数据
                    String data = queue.take();
                    System.out.println("消费数据: " + data);
                    //休眠一秒
                    Thread.sleep(1000);
                }
            } catch (InterruptedException e){
                e.printStackTrace();
            }
        });
        //启动生产者和消费者线程
        producer.start();
        consumer.start();
    }
}
